#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>

/*
 * 是标准C库中用于操作自定义信号集的一个函数
 */

#if 0

# 用于检查一个指定的信号是否在给定的信号集中,也就是检查该信号是否被阻塞
int sigismember(const sigset_t *set, int signum);

    set：指向sigset_t类型的指针，sigset_t是一个信号集类型，表示一个信号集。
    signum：要检查的信号编号。

    如果指定的信号在信号集中，sigismember()函数返回1；如果指定的信号不在信号集中，返回0。
    失败时，返回-1，并设置errno表示错误原因。


# 允许您将一个指定的信号添加到一个自定义信号集中，也就是将该信号的标准位设为1，表示阻塞这个信号
int sigaddset(sigset_t *set, int signum);

    set：指向sigset_t类型的指针，sigset_t是一个信号集类型，表示一个信号集。
    signum：需要添加到信号集中的信号编号。

    成功时，sigaddset()函数返回0；
    失败时，返回-1，并设置errno表示错误原因。

# 允许从一个自定义信号集中删除一个指定的信号，也就是将该信号的标准位设为0，不阻塞这个信号。
int sigdelset(sigset_t *set, int signum);

    set：指向sigset_t类型的指针，sigset_t是一个信号集类型，表示一个信号集。
    signum：需要从信号集中删除的信号编号。

    成功时，sigdelset()函数返回0；
    失败时，返回-1，并设置errno表示错误原因。


# 初始化一个自定义信号集，将其所有信号都清空，也就是将信号集中的所有的标志位置为0，
# 使得这个集合不包含任何信号，也就是不阻塞任何信号。
int sigemptyset(sigset_t *set);

    set：指向sigset_t类型的指针，sigset_t是一个信号集类型，用于表示一个信号集。
         把用这个指针指向的信号集清空，也就是不阻塞任何信号。

    成功时，返回0；
    失败时，返回-1，并设置errno表示错误原因。


#endif

/* 
 * 使用sigaddset()函数创建一个包含SIGINT和SIGTERM信号的信号集 
 */
int add_signal_set() 
{
  sigset_t signal_set;

  // 使用sigemptyset()初始化信号集，清空所有信号
  if (sigemptyset(&signal_set) == -1) {
    perror("sigemptyset");
    return 1;
  }

  // 使用sigaddset()将SIGINT信号添加到信号集中
  if (sigaddset(&signal_set, SIGINT) == -1) {
    perror("sigaddset");
    return 1;
  }

  // 使用sigaddset()将SIGTERM信号添加到信号集中
  if (sigaddset(&signal_set, SIGTERM) == -1) {
    perror("sigaddset");
    return 1;
  }

  // 检查信号集中是否包含SIGINT和SIGTERM信号
  int result1 = sigismember(&signal_set, SIGINT);
  int result2 = sigismember(&signal_set, SIGTERM);
  if (result1 == -1 || result2 == -1) {
    perror("sigismember");
    return 1;
  } else if (result1 == 1 && result2 == 1) {
    printf("SIGINT and SIGTERM are in the signal set.\n");
  }

  return 0;
}

/*
 * 使用sigdelset()函数从信号集中删除SIGINT信号
 */
int del_signal_set() 
{
  sigset_t signal_set;

  // 使用sigfillset()初始化信号集，包含所有可接受的信号
  if (sigfillset(&signal_set) == -1) {
    perror("sigfillset");
    return 1;
  }

  // 使用sigdelset()从信号集中删除SIGINT信号
  if (sigdelset(&signal_set, SIGINT) == -1) {
    perror("sigdelset");
    return 1;
  }

  // 检查信号集中是否包含SIGINT信号
  int result = sigismember(&signal_set, SIGINT);
  if (result == -1) {
    perror("sigismember");
    return 1;
  } else if (result == 0) {
    printf("SIGINT is not in the signal set.\n");
  } else {
    printf("SIGINT is in the signal set.\n");
  }

  return 0;
}

void show_handler(int sig)
{
    printf("I got signal %d\n", sig);
    int i;
    for(i = 0; i < 5; i++) 
   {
        printf("i = %d\n", i);
        sleep(1);
    }
}
 
int main(void)
{
    int i = 0;
    struct sigaction act, oldact;
    act.sa_handler = show_handler;
    sigaddset(&act.sa_mask, SIGQUIT);         
    act.sa_flags = SA_RESETHAND | SA_NODEFER;   // note 1 
    //act.sa_flags = 0;                      
 
    sigaction(SIGINT, &act, &oldact);
    while(1) {
        sleep(1);
        printf("sleeping %d\n", i);
        i++;
    }
}


#if 0

1.如果在信号SIGINT(Ctrl + c)的信号处理函数show_handler执行过程中，本进程收到信号SIGQUIT(Crt+\)，
  将阻塞该信号，直到show_handler执行结束才会处理信号SIGQUIT。

#endif
